package com.devehx.wallet.task;


import com.devehx.wallet.comm.CollectKit;
import com.devehx.wallet.comm.WalletKit;
import com.devehx.wallet.model.Recharge;
import com.devehx.wallet.serviceimpl.RechargeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.web3j.protocol.core.methods.response.EthBlock;
import org.web3j.utils.Numeric;

import javax.annotation.Resource;
import java.math.BigInteger;
import java.util.Objects;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
public class RechargeCheckTask {

    @Resource
    private RechargeCheckTask rechargeTask;

    @Resource
    private RechargeService rechargeService;

    private static final ThreadPoolExecutor POOL = new ThreadPoolExecutor(4, 6, 3, TimeUnit.SECONDS, new ArrayBlockingQueue<>(3));

    @Scheduled(fixedDelay = 2000)
    public void recharge() {
        //最新的区块号码
        int blockNumber = Objects.requireNonNull(WalletKit.getBlockNumber()).intValue();
        //当前扫描的区块号码
        int blockNumberDb = rechargeService.blockNumber();
//        log.info("扫过最新区块号:{},链上最新区块号:{}", blockNumberDb, blockNumber);
        //如果上一次的区块高度是null/0的话就从最新的开始扫
        if (blockNumberDb == 0) {
            rechargeService.updateNumber(blockNumber);
            return;
        }
        if (blockNumber - blockNumberDb <= 5) {
//            log.info("当前最新区块：{}，已经扫描的区块{}，不进行扫描", blockNumber, blockNumberDb);
            return;
        }
        for (int i = blockNumberDb; i < (blockNumber - 3); i++) {
            CountDownLatch latch = new CountDownLatch(4);
            final int one = i;
            final int two = i + 1;
            final int three = i + 2;
            final int four = i + 3;
            POOL.execute(() -> {
                rechargeTask.doRecharge(one);
                latch.countDown();
            });
            POOL.execute(() -> {
                rechargeTask.doRecharge(two);
                latch.countDown();
            });
            POOL.execute(() -> {
                rechargeTask.doRecharge(three);
                latch.countDown();
            });
            POOL.execute(() -> {
                rechargeTask.doRecharge(four);
                latch.countDown();
            });
            try {
                latch.await();
                i = i + 3;
                //扫描完成后把数据库的区块号改成最新的
                rechargeService.updateNumber(four);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }


    public void doRecharge(int blockNumChain) {
        try {
            //区块
            EthBlock.Block block = WalletKit.getBlockByNumber(blockNumChain);
            if (null == block) {
                return;
            }
            log.info("当前扫描的区块号码：" + block.getNumber().toString());
            for (EthBlock.TransactionResult transaction : block.getTransactions()) {
                if (!(transaction instanceof EthBlock.TransactionObject)) {
                    continue;
                }
                //块中的单笔交易
                EthBlock.TransactionObject tx = (EthBlock.TransactionObject) transaction;
                //交易的收款地址
                String to = tx.getTo();
                //收款人是空的话可能就是部署合约，不做操作
                if (null == to) {
                    //return
                    continue;
                }
                String from = tx.getFrom();
                String hash = tx.getHash();
                BigInteger amount = tx.getValue();
                //如果amount大于0就是以太币交易，否则就是代币交易
                if (amount.compareTo(BigInteger.ZERO) > 0) {
                    //收款地址是否在本平台，不在就return
                    if (!rechargeService.isAddress(to)) {
                        continue;
                    }
                    //保存充值记录
                    Recharge recharge = new Recharge("eth", hash, from, to, amount);
                    rechargeService.saveRechargeRecord(recharge);
                } else {
                    String input = tx.getInput();
                    //从input data中取出前缀判断是否是转账的方法，如果不是转账的方法就跳过
                    if (input.length() != 138 || !"0xa9059cbb".equalsIgnoreCase(input.substring(0, 10))) {
                        continue;
                    }
                    //从input data中获取出收款地址
                    String to1 = "0x" + input.substring(34, 74);
                    //转账数量（单位是wei）
                    BigInteger amount1 = Numeric.toBigInt(input.substring(74));
                    if (!rechargeService.isCoin(to)) {
                        continue;
                    }
                    //收款地址是否在本平台，不在就return
                    if (!rechargeService.isAddress(to1)) {
                        continue;
                    }
                    //保存充值记录
                    Recharge recharge = new Recharge(to, hash, from, to1, amount1);
                    rechargeService.saveRechargeRecord(recharge);
                    CollectKit.remove(to);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("扫快出错", e);
        }
    }

}
